package main

import (
	"fmt"
	"flag"
	"encoding/json"
	"time"
	"strconv"
	"os"
	"io/ioutil"
	"crypto/md5"
	"encoding/hex"
	"strings"
	"net/http"
	"bytes"
)

type Per struct {
	Name     string
	Position string
}

func main() {
	fmt.Println(os.Args)
	host := flag.String("host", "172.16.2.117", "API server IP")
	port := flag.String("port", "80", "API server port")

	uri := flag.String("uri", "",
		"api uri, example:/api/query/live_app_count")
	body := flag.String("body", "body.json",
		"file path, and file content is body json")
	secret := flag.String("secret", "123456", "app system secret")
	method := flag.String("method", "post", "http method: post only")
	flag.Parse()

	if *uri == "" {
		println("please set uri")
		return
	}
	if *body == "" {
		println("please set body file ")
		return
	}
	newBody, err := makeBody(*body)
	if err != nil {
		return
	}
	sign := makeSign(*secret, *uri, newBody)
	url := makeUrl(*host, *port, *uri, sign)

	execute(url, *method, newBody)
}
func execute(url string, method string,raw string) {
	switch method {
	case "post":
		executePost(url, raw)
	case "put":
	}

}
func executePost(url string, raw string) {
	resp, err := http.Post(url,
		"application/json",
		strings.NewReader(raw))
	if err != nil {
		fmt.Println(err)
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("request fail:", err)
		return
	}
	printResponse(body)
}
func printResponse(body []byte) {
	var out bytes.Buffer
	err := json.Indent(&out, body, "", "\t")

	if err != nil {
		fmt.Println("the http response:", string(body))
		fmt.Print("format fail", err)
		return
	}
	fmt.Println("the http response:")
	out.WriteTo(os.Stdout)
}

func makeBody(input string) (string, error) {
	bodyContent, err := ioutil.ReadFile(input)
	if err != nil {
		fmt.Println("read body content fail, ", err)
		return "", err
	}

	var p map[string]interface{}
	err = json.Unmarshal([]byte(string(bodyContent)), &p)
	if err != nil {
		fmt.Println("body must json,", err)
		return "", err
	}
	timestamp := getCurrentTimestamp()

	printBody("raw body:", p)
	p["timestamp"] = timestamp
	return printBody("dst body:", p)
}

func makeUrl(host string, port string, uri string, sign string) string {
	url := "http://" + host + ":" + port + "" + uri + "?sign=" + sign
	return url
}

func makeSign(secret string, uri string, body string) string {
	tmp := secret + uri + "?body=" + body

	h := md5.New()
	h.Write([]byte(tmp)) // 需要加密的字符串
	cipherStr := h.Sum(nil)
	sign := hex.EncodeToString(cipherStr)
	fmt.Println("sign raw:" + tmp + ", md5:" + sign)
	return sign
}

func getCurrentTimestamp() int64 {
	timestamp := strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
	timestamp = timestamp[:13]
	longTimestamp, _ := strconv.ParseInt(timestamp, 10, 64)
	return longTimestamp
}

func printBody(tip string, body map[string]interface{}) (string, error) {
	distBody, err := json.Marshal(body)
	if err != nil {
		fmt.Println("body must json,", err)
		return "", err
	}
	dist := string(distBody)
	fmt.Println(tip, dist)

	return dist, nil
}
